package net.lastcoder.x;

import net.lastcoder.ifserver.Constants;
import net.lastcoder.ifserver.util.TextUtils;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;

/**
 * 终端控制台
 */
public class Terminate extends IoHandlerAdapter {
    private IoConnector connector;
    private static IoSession session;
    private static String uid;
    private static String password;
    private static String host = "localhost";
    private static int port = 9588;
    final CharsetEncoder encoder = Constants.DEFAUT_CAHRSET.newEncoder()
            .onMalformedInput(CodingErrorAction.REPORT)
            .onUnmappableCharacter(CodingErrorAction.REPORT);
    final CharsetDecoder decoder = Constants.DEFAUT_CAHRSET.newDecoder()
            .onMalformedInput(CodingErrorAction.REPORT)
            .onUnmappableCharacter(CodingErrorAction.REPORT);

    /**
     * Create the UdpClient's instance
     */
    public Terminate() {
        connector = new NioSocketConnector();
        connector.setHandler(this);
        ConnectFuture connFuture = connector.connect(new InetSocketAddress(host, port));
        connFuture.awaitUninterruptibly();

        session = connFuture.getSession();
        session.getConfig().setWriterIdleTime(1000 * 60 * 3);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        cause.printStackTrace();
        System.err.println(cause);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        IoBuffer ioBuffer = (IoBuffer) message;
        ioBuffer.mark();
        if (ioBuffer.get() == '\0' && ioBuffer.remaining() == 1) {
            System.err.println("session close");
            session.close(false);
            System.exit(0);
        }
        ioBuffer.rewind();

        IoBuffer buffer = (IoBuffer)message;
        String str = null;
        str = buffer.getString(decoder);
        if (!str.equalsIgnoreCase("pong")) {
            System.out.print(str);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void messageSent(IoSession session, Object message) throws Exception {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void sessionClosed(IoSession session) throws Exception {
        System.exit(0);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void sessionCreated(IoSession session) throws Exception {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
        if (status == IdleStatus.WRITER_IDLE) {
            send("ping");
        }
    }

    /** 
     * {@inheritDoc}
     */
    @Override
    public void sessionOpened(IoSession session) throws Exception {
        send("login " + uid + " " + password);
    }

    /**
     * The main method : instanciates a client, and send N messages. We sleep 
     * between each K messages sent, to avoid the server saturation.
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            System.out.println("use like: \" ifservertel [uid] [password] [host] [port] \" ");
            return;
        }

        uid = args[0];
        if (uid.equals("-h") || uid.equals("--help")) {
            System.out.println("use like: \" ifservertel [uid] [password] [host] [port] \" ");
            return;
        }

        password = args[1];
        if (args.length >= 3) {
            host = args[2];
        }
        if (args.length >= 4) {
            port = Integer.parseInt(args[3]);
        }

    	Terminate client = new Terminate();

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str;
        boolean isExit = false;
        while (!isExit) {
            try {
                if (br.ready()) {
                    str = br.readLine();
                    if (TextUtils.isEmpty(str)) {
                        continue;
                    }
                    if (str.equalsIgnoreCase("playerExit")) {
                        client.send(str);
                        break;
                    }
                    client.send(str);
                }
            } catch (IOException ioe) {
                System.err.println("error input, " + ioe.getMessage());
            } catch (Exception e) {
                System.err.println("process error : " + e.getMessage());
            }
        }

        client.connector.dispose(true);
    }

    private void send(String str) {
        IoBuffer buffer = IoBuffer.allocate(4 * 1024);
        try {
            buffer.putString(str, encoder);
        } catch (CharacterCodingException e) {
            e.printStackTrace();
        }
        buffer.flip();
        session.write(buffer);
    }
}
